package com.atguigu.gmall.order.service;

import com.alibaba.fastjson.JSON;
import com.atguigu.gmall.cart.vo.Cart;
import com.atguigu.gmall.common.bean.ResponseVo;
import com.atguigu.gmall.oms.vo.OrderItemVo;
import com.atguigu.gmall.oms.vo.OrderSubmitVo;
import com.atguigu.gmall.order.exection.OrderExection;
import com.atguigu.gmall.order.feign.*;
import com.atguigu.gmall.order.interceptor.OrderInterceptor;
import com.atguigu.gmall.order.vo.OrderConfirmVo;
import com.atguigu.gmall.pms.entity.SkuAttrValueEntity;
import com.atguigu.gmall.pms.entity.SkuEntity;
import com.atguigu.gmall.sms.vo.ItemSaleVo;
import com.atguigu.gmall.sms.vo.SkuSaleVo;
import com.atguigu.gmall.ums.entity.UserAddressEntity;
import com.atguigu.gmall.ums.entity.UserEntity;
import com.atguigu.gmall.wms.entity.WareSkuEntity;
import com.atguigu.gmall.wms.vo.SkuLockVo;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.JdkIdGenerator;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class OrderService {

    @Autowired
    GmallUmsClient gmallUmsClient;

    @Autowired
    GmallWmsClient gmallWmsClient;

    @Autowired
    GmallPmsClient gmallPmsClient;

    @Autowired
    GmallSmsClient gmallSmsClient;

    @Autowired
    GmallOmsClient omsClient;

    @Autowired
    GmallCartClient cartClient;

    @Autowired
    StringRedisTemplate redisTemplate;

    @Autowired
    RabbitTemplate rabbitTemplate;

    private static final String KEY_PREFIX = "order:token:";

    public OrderConfirmVo OrderTrade() {
        // 1.获取用户地址信息
        Long userId = OrderInterceptor.getUserInfo().getUserId();
        ResponseVo<List<UserAddressEntity>> listResponseVo = gmallUmsClient.queryUserAddressByUserId(userId);
        List<UserAddressEntity> userAddressEntities = listResponseVo.getData();
        OrderConfirmVo confirmVo = new OrderConfirmVo();
        confirmVo.setAddresses(userAddressEntities);

        // 2.查询商品信息
        ResponseVo<List<Cart>> listResponseVo1 = cartClient.queryCartByUserId(userId);
        List<Cart> carts = listResponseVo1.getData();
        if (!CollectionUtils.isEmpty(carts)){
            List<OrderItemVo> orderItemVos = carts.stream().map(cart -> {
                OrderItemVo orderItemVo = new OrderItemVo();
                orderItemVo.setCount(cart.getCount());
                orderItemVo.setSkuId(cart.getSkuId());
                //查询sku基本信息
                ResponseVo<SkuEntity> skuEntityResponseVo = gmallPmsClient.querySkuById(cart.getSkuId());
                SkuEntity skuEntity = skuEntityResponseVo.getData();
                BeanUtils.copyProperties(skuEntity, orderItemVo);
                // 查询sku商品的库存信息
                ResponseVo<List<WareSkuEntity>> wareSkusBySkuId = gmallWmsClient.queryWareSkusBySkuId(cart.getSkuId());
                List<WareSkuEntity> wareSkuEntities = wareSkusBySkuId.getData();
                boolean b = wareSkuEntities.stream().anyMatch(wareSkuEntity -> wareSkuEntity.getStock() - wareSkuEntity.getStockLocked() > 0);
                orderItemVo.setStore(b);

                // 查询sku的营销信息
                ResponseVo<List<ItemSaleVo>> itemSaleBySkuId = gmallSmsClient.queryItemSaleBySkuId(cart.getSkuId());
                List<ItemSaleVo> saleBySkuIdData = itemSaleBySkuId.getData();
                if (!CollectionUtils.isEmpty(saleBySkuIdData)) {
                    orderItemVo.setSales(saleBySkuIdData);
                }
                // 查询sku的销售属性
                List<SkuAttrValueEntity> skuAttrValueEntities = gmallPmsClient.querySaleAttrValuesBySkuId(cart.getSkuId()).getData();
                if (!CollectionUtils.isEmpty(skuAttrValueEntities)) {
                    orderItemVo.setSaleAttrs(skuAttrValueEntities);
                }
                return orderItemVo;
            }).collect(Collectors.toList());
            confirmVo.setItems(orderItemVos);
        }else {
            throw new OrderExection("你没有要购买的商品");
        }
        // 3.查询用户的购物积分
        UserEntity userEntity = gmallUmsClient.queryUserById(userId).getData();
        confirmVo.setBounds(userEntity.getIntegration());
        // 4.生成防重令牌
        String idStr = IdWorker.getIdStr();
        confirmVo.setOrderToken(idStr);
        redisTemplate.opsForValue().set(KEY_PREFIX+idStr,idStr,3, TimeUnit.HOURS);
        return confirmVo;
    }

    /*
    提交订单
     */
    public void submit(OrderSubmitVo orderSubmitVo) {
        // 1.防止重复提交
        String orderToken = orderSubmitVo.getOrderToken();
        if (StringUtils.isEmpty(orderToken)){
            throw new OrderExection("非法请求！");
        }
        String token = "if redis.call('get',KEYS[1])==ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end";
        Boolean aBoolean = redisTemplate.execute(new DefaultRedisScript<>(token, Boolean.class), Arrays.asList(KEY_PREFIX + orderToken), orderToken);
        if (!aBoolean){
            throw new OrderExection("请不要重复提交！");
        }

        // 2.验价
        BigDecimal totalPrice = orderSubmitVo.getTotalPrice();
        List<OrderItemVo> items = orderSubmitVo.getItems();
        BigDecimal bigDecimal = items.stream().map(item -> {
            ResponseVo<SkuEntity> responseVo = gmallPmsClient.querySkuById(item.getSkuId());
            SkuEntity skuEntity = responseVo.getData();
            if (skuEntity == null) {
                return new BigDecimal(0);
            }
            return skuEntity.getPrice().multiply(item.getCount());
        }).reduce((a, b) -> a.add(b)).get();
        if (totalPrice.compareTo(bigDecimal)!=0){
            throw new OrderExection("页面已过期，请刷新后重试！");
        }
        // 3.锁库存
        List<SkuLockVo> skuLockVos = items.stream().map(item -> {
            SkuLockVo skuLockVo = new SkuLockVo();
            skuLockVo.setCount(item.getCount().intValue());
            skuLockVo.setSkuId(item.getSkuId());
            return skuLockVo;
        }).collect(Collectors.toList());
        ResponseVo<List<SkuLockVo>> listResponseVo = gmallWmsClient.checkLock(skuLockVos, orderSubmitVo.getOrderToken());
        List<SkuLockVo> lockVos = listResponseVo.getData();
        if (!CollectionUtils.isEmpty(lockVos)){
            throw new OrderExection("下单失败");
        }
        // 4.创建订单
        Long userId = OrderInterceptor.getUserInfo().getUserId();
        try {
            omsClient.saveOrder(orderSubmitVo,userId);
            //定时关单
            this.rabbitTemplate.convertAndSend("ORDER_EXCHANGE", "order.ttl", orderToken);
        } catch (Exception e) {
            e.printStackTrace();
            // TODO 发送消息解锁库存和修改订单状态
            this.rabbitTemplate.convertAndSend("ORDER_EXCHANGE","order.failer",orderToken);
        }
        // 5.删除购物车中的数据 异步
        List<Long> longs = items.stream().map(item -> item.getSkuId()).collect(Collectors.toList());
        Map<String,Object> map = new HashMap<>();
        map.put("userId",userId);
        map.put("skuIds", JSON.toJSONString(longs));
        //删除购物车中的商品信息
        rabbitTemplate.convertAndSend("ORDER_EXCHANGE","cart.del",map);

    }
}
